#pragma once
#include "Stack_list.h"
#include "history.h"

//没有棋子用零代替
#define NO_PIECE   0
//依次定义红帅炮車象仕马兵
#define R_KING     1
#define R_CANNON   2
#define R_CAR      3
#define R_ELEPHANT 4
#define R_GUARD    5
#define R_HORSE    6
#define R_SOLDIER  7

//依次定义黑帅炮車象仕马兵
#define B_KING     11
#define B_CANNON   12
#define B_CAR      13
#define B_ELEPHANT 14
#define B_GUARD    15
#define B_HORSE    16
#define B_SOLDIER  17

//执子玩家
#undef RED
#undef BLACK
#define RED true
#define BLACK false

//帅状态
#define NO_R_KING 1        //红帅无
#define NO_B_KING -1       //黑帅无
#define RB_KING_ALL_HAVE 0 //都有

#define STATE_ 0 //都有

//处理索引
//合并索引
#define indexIndex(fromIndex,toIndex) (1000 * (fromIndex) + (toIndex))
//分开索引
#define fromIndex(index) ((index) / 1000)
#define toIndex(index) ((index) % 1000)

//根据索引获取坐标与根据坐标获取索引
#define getX(index) ((index) % 13 - 2)
#define getY(index) ((index) / 13)
#define getIndex(x, y) (13 * (y) + (x) + 2)

const static int kingPositionValue[10][9] = {
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 1, 1, 1, 0, 0, 0},
							{0, 0, 0, 2, 2, 2, 0, 0, 0},
							{0, 0, 0, 11, 15, 11, 0, 0, 0} };


const static int guardPositionValue[10][9] = {
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 20, 0, 20, 0, 0, 0},
							{0, 0, 0, 0, 23, 0, 0, 0},
							{0, 0, 0, 20, 0, 20, 0, 0, 0} };


const static int elephantPositionValue[10][9] = {
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 20, 0, 0, 0, 20, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{18, 0, 0, 0, 23, 0, 0, 0, 18},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 20, 0, 0, 0, 20, 0, 0} };


const static int horsePositionValue[10][9] = {
							{90, 90, 90, 96, 90, 96, 90, 90, 90},
							{90, 96, 103, 97, 94, 97, 103, 96, 90},
							{92, 98, 99, 103, 99, 103, 99, 98, 92},
							{93, 108, 100, 107, 100, 107, 100, 108, 93,},
							{90, 100, 99, 103, 104, 103, 99, 100, 90, },
							{90, 98, 101, 102, 103, 102, 101, 98, 90, },
							{92, 94, 98, 95, 98, 95, 98, 94, 92,},
							{93, 92, 94, 95, 92, 95, 94, 92, 93,},
							{85, 90, 92, 93, 78, 93, 92, 90, 85,},
							{88, 85, 90, 88, 90, 88, 90, 85, 88 } };



const static int carPositionValue[10][9] = {
							{206, 208, 207, 213, 214, 213, 207, 208, 206},
							{206, 212, 209, 216, 233, 216, 209, 212, 206},
							{206, 208, 207, 214, 216, 214, 207, 208, 206},
							{206, 213, 213, 216, 216, 216, 213, 213, 206},
							{208, 211, 211, 214, 215, 214, 211, 211, 208},
							{208, 212, 212, 214, 215, 214, 212, 212, 208},
							{204, 209, 204, 212, 214, 212, 204, 209, 204},
							{198, 208, 204, 212, 212, 212, 204, 208, 198},
							{200, 208, 206, 212, 200, 212, 206, 208, 200},
							{194, 206, 204, 212, 200, 212, 204, 206, 194} };

const static int cannonPositionValue[10][9] = {
							{100, 100, 96, 91, 90, 91, 96, 100, 100},
							{98, 98, 96, 92, 89, 92, 96, 98, 98},
							{97, 97, 96, 91, 92, 91, 96, 97, 97},
							{96, 99, 99, 98, 100, 98, 99, 99, 96},
							{96, 96, 96, 96, 100, 96, 96, 96, 96},
							{95, 96, 99, 96, 100, 96, 99, 96, 95},
							{96, 96, 96, 96, 96, 96, 96, 96, 96},
							{97, 96, 100, 99, 101, 99, 100, 96, 97},
							{96, 97, 98, 98, 98, 98, 98, 97, 96},
							{96, 96, 97, 99, 99, 99, 97, 96, 96} };

const static int soldierPositionValue[10][9] = {
							{9, 9, 9, 11, 13, 11, 9, 9, 9},
							{19, 24, 34, 42, 44, 42, 34, 24, 19},
							{19, 24, 32, 37, 37, 37, 32, 24, 19},
							{19, 23, 27, 29, 30, 29, 27, 23, 19},
							{14, 18, 20, 27, 29, 27, 20, 18, 14},
							{7, 0, 13, 0, 16, 0, 13, 0, 7},
							{7, 0, 7, 0, 15, 0, 7, 0, 7},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0},
							{0, 0, 0, 0, 0, 0, 0, 0, 0} };


class Chess
{
private:
	//棋子存在这个一维数组里面y是下标/3 x是下标%13
	//左右多出来的两列是用来判定出界的，上下没多是因为判断index与0和129的关系就行了
	short board[130];

	short kingState = RB_KING_ALL_HAVE;

	//执子玩家，红true黑false
	bool nowPlayer = RED;

	short state = 0;//游戏状态

	//历史记录（新的记录会被加到前面）
	History* previousMove;
	Stack_list<History*, 200> historyPool;

	inline bool indexHaveSelf(const short index, const short piece);
	inline bool indexHaveEnemy(const short index, const short piece);


	Stack_list<int, 250> validMoves;


	//添加到走法，带校验函数和不带的
	void addToValidMove(int fromIndex, int toIndex, bool (*isValidPosition)(int));
	void addToValidMove(int fromIndex, int toIndex);
public:
	Chess();                     //构造棋盘的构造函数，会创建一个棋盘，side是电脑的方向
	Chess(bool firstPlay);       //跟空参构造函数一样的功能，但是初始化会带上谁先手

	//获取和设置游戏状态
	short getState();
	void setState(short i);

	//坐标处是否有棋子
	bool xyHavePiece(int x, int y);
	bool indexHavePiece(const int index);

	//获取指定坐标的棋子
	short getPiece(int x, int y);
	short getIndexPiece(const int index);

	//获取执子玩家
	bool getNowPlayer();

	//获取将的状态
	int getKingState();


	//走棋
	void move(int fromX, int fromY, int toX, int toY);
	void move(int indexIndex);
	bool canMove(int fromX, int fromY, int toX, int toY);

	//回退
	bool rollBack();

	//遍历棋盘
	void forBoard(void fun(int range, short piece));

	int getTotalValue(bool side);

	//返回一个validMoves集合，每个走法是一个int型的两个index，前from后to fffttt每个占三位
	Stack_list<int, 250> getValidMoves(bool side);
	bool isInCheck(bool side);    //判定是否被将军,参数传红方还是黑方
};

int getTotalValue(Chess* chess, bool side);//获取一方的价值评分
int minMaxSearch(Chess* chess, bool minOrMax, int boundary, bool side, short deep, int& move);



//校验位置是否合法
bool isInBoard(int index);
bool isValidRKingRGuardPosition(int index);
bool isValidRELEPHANTPosition(int index);
bool isValidBKingBGuardPosition(int index);
bool isValidBELEPHANTPosition(int index);